跳至主要内容

【教程】從零開始搭建 k3s 集群

k3s 高可用集群封面圖

提示:本教程基於 Linux + fish shell 編寫,個別命令語法與 Bash 略有差異。請結合自己的系統環境調整命令。

引言

眾所周知,k3s 是由 Rancher Labs 開發的輕量級 Kubernetes 發行版,也是目前最流行的 K8s 輕量化方案。

相較於傳統運維方式(1Panel/寶塔/SSH 等),k3s 的學習曲線更陡峭,需要理解更多容器編排概念。但一旦掌握,你將獲得:

k3s 的核心優勢

  • 輕量高效 - 單個二進制文件,內存佔用 < 512MB,完美適配低配 VPS
  • 生產就緒 - 完全兼容 Kubernetes API,可平滑遷移到標準 K8s
  • 聲明式運維 - 用 YAML 描述期望狀態,系統自動維護
  • 高可用保障 - 自動故障恢復 + 多節點負載均衡
  • 開箱即用 - 內置網絡、存儲、Ingress 等核心組件

通過 k3s,我們可以將多台廉價 VPS 整合為企業級高可用集群,實現傳統運維難以達到的自動化水平。

目標讀者與準備

適合人群

  • 有一定 Linux 基礎的開發者
  • 希望從傳統運維過渡到容器編排
  • 想搭建個人高可用服務的技術愛好者

前置知識

  • 熟悉 Linux 命令行操作
  • 了解 Docker 容器基礎
  • 具備基本的網絡知識(SSH、防火牆)

學習收獲

完成本教程後,你將掌握:

  1. 使用 k3sup 快速部署 k3s 集群
  2. 理解 k3s 核心組件(API Server、etcd、kubelet 等)的作用
  3. 替換默認組件優化性能(Cilium CNI、Nginx Ingress 等)
  4. 部署第一個應用並配置外部訪問
  5. 基本的集群運維和故障排查技巧

部署規劃

k3s 默認安裝了一套精簡組件,為了滿足生產級訴求,我們需要提前規劃哪些模塊要保留或替換。下表展示了推薦的取捨策略:

組件類型k3s 默認組件替換組件替換理由k3sup 禁用參數
容器運行時containerd-保持默認即可-
數據存儲SQLite / etcd-單節點用 SQLite,集群用 etcd-
Ingress ControllerTraefikNginx Ingress / 其他團隊更熟悉、功能需求不同--disable traefik
LoadBalancerService LB (Klipper-lb)不想部署懶得管負載均衡,直接買 cloudflare--disable servicelb
DNSCoreDNS-保持默認即可-
Storage ClassLocal-path-provisionerLonghorn分佈式存儲、高可用、備份能力--disable local-storage
CNIFlannelCiliumeBPF 性能、網絡策略、可觀測性--flannel-backend=none --disable-network-policy

k3s 默認組件與替換方案對比表

環境準備

必備工具

首先,確保 k3sup、kubectl、Helm 等工具已正確安裝(可參考各自 GitHub 項目提供的安裝說明):

k3sup version
kubectl version
helm version

如圖所示:

工具安裝版本檢查截圖

服務器要求

準備至少三台雲服務器(示例環境使用 Ubuntu 24.04),作為最小化三節點高可用控制平面(推薦配置 ≥ 4C4G)。提前記錄各節點 IP、確認 SSH 公鑰已分發,並知曉本地私鑰路徑,後續步驟會用到。

部署初始控制平面

使用 k3sup 部署初始控制節點:

k3sup install \
--ip 初始節點 IP \
--user root \
--ssh-key 密鑰位置 \
--k3s-channel latest \
--cluster \
--k3s-extra-args "--disable traefik --disable servicelb --disable local-storage --flannel-backend=none --disable-network-policy"

如圖所示: k3sup 安裝初始控制節點輸出

安裝完成後,k3sup 會自動將 kubeconfig 複製到當前目錄。雖然可以直接使用這份配置,但更加穩健的做法是與現有配置文件合併。

合併 kubeconfig

  1. 備份當前的 kubeconfig(默認位於 ~/.kube/config):
cp ~/.kube/config ~/.kube/config.backup

fish shell(僅供參考):

cp $KUBECONFIG {$KUBECONFIG}.backup
  1. 將新舊 kubeconfig 合併為一份扁平文件:
KUBECONFIG=~/.kube/config:./kubeconfig kubectl config view --flatten > ~/.kube/config.new

fish shell(僅供參考):

KUBECONFIG=$KUBECONFIG:./kubeconfig kubectl config view --flatten > kubeconfig-merged.yaml
  1. 檢查新文件內容無誤後覆蓋舊配置:
mv ~/.kube/config.new ~/.kube/config

fish shell

mv ./kubeconfig-merged.yaml $KUBECONFIG
  1. 驗證新上下文是否生效:
kubectl config get-contexts
kubectl config use-context default

安裝 Cilium(替代 Flannel)

安裝 k3s 時我們禁用了默認 CNI(Flannel),因此節點暫時無法互通。按計劃部署 Cilium 以提供網絡與網絡策略能力。

使用 Helm 安裝 Cilium:

# 添加 Cilium Helm 倉庫
helm repo add cilium https://helm.cilium.io/

# 更新 Helm 倉庫
helm repo update

# 安裝 Cilium CNI(單副本,默認模式)
helm install cilium cilium/cilium \
--namespace kube-system \
--set operator.replicas=1 \
--set ipam.mode=kubernetes

如果集群已經禁用 kube-proxy,可額外添加 --set kubeProxyReplacement=strict。本教程保持默認值以兼容更多場景。

執行完成後可以看到: Helm 安裝 Cilium 終端輸出 Cilium Pod 與節點狀態檢查輸出

等待 Cilium 組件啟動完成:

# 查看 Cilium 相關 Pod 狀態
kubectl get pods -n kube-system -l k8s-app=cilium

# 查看節點狀態(應該從 NotReady 變為 Ready)
kubectl get nodes

kubectl 控制平面節點已就緒截圖

節點切換到 Cilium 後應當從 NotReady 變為 Ready。接下來使用 k3sup 加入另外兩個控制節點。

擴容控制平面

為了實現高可用,我們需要至少 3 個控制節點。使用以下命令加入第二個控制節點:

k3sup join \
--ip 第二個節點 IP \
--user root \
--ssh-key 密鑰位置 \
--server-ip 初始節點 IP \
--server \
--k3s-channel latest \
--k3s-extra-args "--disable traefik --disable servicelb --disable local-storage --flannel-backend=none --disable-network-policy"

同樣的方式加入第三個控制節點:

k3sup join \
--ip 第三個節點 IP \
--user root \
--ssh-key 密鑰位置 \
--server-ip 初始節點 IP \
--server \
--k3s-channel latest \
--k3s-extra-args "--disable traefik --disable servicelb --disable local-storage --flannel-backend=none --disable-network-policy"

等待幾分鐘後檢查集群狀態:

kubectl get nodes

當三個控制節點均處於 Ready 狀態時,控制平面即告搭建完成。

加入更多控制節點後的集群狀態

安裝 Nginx Ingress Controller

替換 k3s 默認的 Traefik,安裝 Nginx Ingress Controller:

# 添加 Nginx Ingress Helm 倉庫
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update

# 安裝 Nginx Ingress Controller(可能需要等待很久)
helm install ingress-nginx ingress-nginx/ingress-nginx \
--namespace ingress-nginx \
--create-namespace \
--set controller.hostPort.enabled=true \
--set controller.hostPort.ports.http=80 \
--set controller.hostPort.ports.https=443 \
--set controller.service.type=ClusterIP
kubectl get pods -n ingress-nginx
kubectl get svc -n ingress-nginx

Nginx Ingress Controller 組件狀態截圖

安裝 Longhorn 分佈式存儲

Longhorn 是由 Rancher 開發的雲原生分佈式塊存儲系統,提供高可用、備份、快照等企業級功能。相比 k3s 默認的 local-path-provisioner,Longhorn 支持跨節點的持久化存儲。

前置依賴檢查

在安裝 Longhorn 之前,需要確保每個節點都安裝了必要依賴;若希望通過 Ansible 批量處理,可參考後續示例:

# 在每個節點上執行(通過 SSH)
# 檢查並安裝 open-iscsi
apt update
apt install -y open-iscsi nfs-common

# 啟動並設置開機自啟
systemctl enable --now iscsid
systemctl status iscsid

如果希望使用 Ansible 批量安裝依賴,可以參考以下任務片段:

---
- name: Setup K3s nodes with Longhorn dependencies and CrowdSec
hosts: k3s
become: true
vars:
crowdsec_version: "latest"

tasks:
# ============================================
# Longhorn Prerequisites
# ============================================
- name: Install Longhorn required packages
ansible.builtin.apt:
name:
- open-iscsi # iSCSI support for volume mounting
- nfs-common # NFS support for backup target
- util-linux # Provides nsenter and other utilities
- curl # For downloading and API calls
- jq # JSON processing for Longhorn CLI
state: present
update_cache: true
tags: longhorn

- name: Enable and start iscsid service
ansible.builtin.systemd:
name: iscsid
enabled: true
state: started
tags: longhorn

- name: Load iscsi_tcp kernel module
community.general.modprobe:
name: iscsi_tcp
state: present
tags: longhorn

- name: Ensure iscsi_tcp loads on boot
ansible.builtin.lineinfile:
path: /etc/modules-load.d/iscsi.conf
line: iscsi_tcp
create: true
mode: '0644'
tags: longhorn

- name: Check if multipathd is installed
ansible.builtin.command: which multipathd
register: multipathd_check
failed_when: false
changed_when: false
tags: longhorn

- name: Disable multipathd if installed (conflicts with Longhorn)
ansible.builtin.systemd:
name: multipathd
enabled: false
state: stopped
when: multipathd_check.rc == 0
tags: longhorn

部署 Longhorn

使用 Helm 安裝 Longhorn:

# 添加 Longhorn Helm 倉庫
helm repo add longhorn https://charts.longhorn.io
helm repo update

# 安裝 Longhorn(可能需要等待較長時間),請注意這裡為了節約硬盤空間,只設置了單副本,請根據需求自行調整
helm install longhorn longhorn/longhorn \
--namespace longhorn-system \
--create-namespace \
--set defaultSettings.defaultDataPath="/var/lib/longhorn" \
--set persistence.defaultClass=true \
--set persistence.defaultClassReplicaCount=1

等待 Longhorn 組件啟動:

# 查看 Longhorn 組件狀態
kubectl get pods -n longhorn-system

# 查看 StorageClass
kubectl get storageclass

Longhorn 組件運行狀態截圖 Longhorn 存儲類列表截圖

訪問 Longhorn UI(可選)

Longhorn 提供了一個 Web UI 用於管理存儲卷。可以通過端口轉發臨時訪問:

# 端口轉發到本地
kubectl port-forward -n longhorn-system svc/longhorn-frontend 8081:80

# 在瀏覽器訪問 http://localhost:8081

完成查看後,請在終端按 Ctrl+C 停止端口轉發,避免持續佔用本地端口。

加入 Agent 節點

目前為止,我們搭建了一個 3 節點的高可用控制平面(control-plane)。在生產環境中,我們不希望在 control-plane 節點上運行實際的應用程序(會佔用 API Server、etcd 等核心組件的資源)。

因此,我們需要加入專門用於運行工作負載(Pods)的 Agent 節點(也稱為 Worker 節點)。

安裝前置依賴

與 control-plane 節點一樣,Agent 節點也需要滿足 Longhorn 的依賴(若希望這些節點能夠調度並存儲持久卷)。

在所有準備加入的 Agent 節點上,提前執行以下命令:

# 在每個 Agent 節點上執行(通過 SSH)
apt update
apt install -y open-iscsi nfs-common

# 啟動並設置開機自啟
systemctl enable --now iscsid

執行加入命令

添加 Agent 節點的命令與添加 control-plane 節點幾乎一致,但有兩個關鍵區別:不使用 --server 標記且無需額外參數。

k3sup join \
--ip <AGENT_節點 IP> \
--user root \
--ssh-key <密鑰位置> \
--server-ip <任意 Control 節點 IP> \
--k3s-channel latest

驗證節點狀態

可以一次性加入多個 Agent 節點。添加完成後等待幾分鐘,Cilium 與 Longhorn 的組件會自動調度到新節點。

使用 kubectl 查看集群狀態:

kubectl get nodes -o wide

你應該能看到新加入的節點,其 ROLE 列顯示為 <none>(在 k3s 中,<none> 即代表 agent/worker 角色)。 同時,你可以監控 Cilium 和 Longhorn 的 Pod 是否在新節點上成功啟動:

# Cilium agent 應該會在新節點上啟動
kubectl get pods -n kube-system -o wide

# Longhorn instance-manager 應該也會在新節點上啟動
kubectl get pods -n longhorn-system -o wide

至此,集群已經擁有了高可用的控制平面和用於運行應用的工作節點。

下一步行動

  • 配置 Argo CD、Flux 等 GitOps 工具,將集群聲明式管理流程標準化。
  • 部署 Prometheus、Loki、Grafana 等可觀測性組件,完善監控與日誌體系。
  • 使用 Ansible Playbook 自動化節點初始化與組件升級,降低後續運維成本。

參考資料